package com.iceberg.database;

import lombok.experimental.UtilityClass;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.function.Supplier;

@UtilityClass
public class TransactionUtil {

    /**
     * 将方法封装在事务里，
     * 事务传播级别-REQUIRED
     *
     * @deprecated 请使用doInTransactionRequired方法
     */
    @Deprecated
    public <T> T doInTransaction(Supplier<T> supplier) {
        return doInTransactionRequired(supplier);
    }

    /**
     * 将方法封装在事务里，
     * 事务传播级别-REQUIRED
     */
    public <T> T doInTransactionRequired(Supplier<T> supplier) {
        DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
        transDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);

        PlatformTransactionManager transactionManager = SpringContextHolder.getBean("transactionManager", PlatformTransactionManager.class);
        TransactionStatus status = transactionManager.getTransaction(transDefinition);
        T result = null;
        try {
            result = supplier.get();
            transactionManager.commit(status);
        } catch (Throwable ex) {
            transactionManager.rollback(status);
            throw ex;
        }
        return result;
    }

    /**
     * 将方法封装在事务里，
     * 事务传播级别-REQUIRES_NEW
     */
    public <T> T doInTransactionRequiresNew(Supplier<T> supplier) {
        DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
        transDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);

        PlatformTransactionManager transactionManager = SpringContextHolder.getBean("transactionManager", PlatformTransactionManager.class);
        TransactionStatus status = transactionManager.getTransaction(transDefinition);
        T result = null;
        try {
            result = supplier.get();
            transactionManager.commit(status);
        } catch (Throwable ex) {
            transactionManager.rollback(status);
            throw ex;
        }
        return result;
    }
}
